Skip to content

Encode path option get and update - #243

Merged
phanak-sap merged 9 commits into
SAP:masterfrom
linda-sap:encode-path-option-get-and-update
Apr 16, 2023
Merged

phanak-sap merged 9 commits into
SAP:masterfrom
linda-sap:encode-path-option-get-and-update

Conversation

@linda-sap

Copy link
Copy Markdown
Contributor

Sometimes services expect the path to be percent encoded. This can especially be important
when special variable types are key fields like Date type, where a ':' will appear in the path.
In this case you can use an optional parameter to make the request encode the path.
Per default the variable encode_path is set to False.

@cla-assistant

cla-assistant Bot commented Mar 8, 2023 •

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@jfilak

jfilak commented Mar 8, 2023

Copy link
Copy Markdown
Contributor

@linda-sap Welcome to the contributors. This is a nice pull request. Could you just explain why is the encoding optional? Isn't just a bug to not always encode it?

@linda-sap

Copy link
Copy Markdown
Contributor Author

@jfilak Thanks :) I currently can't think of a case where it shouldn't be encoded, rather just to not crash any existing use, where it might be expected unencoded. Would you opt for making it always encode or maybe to make the encoding the default?

@jfilak

jfilak commented Mar 8, 2023

Copy link
Copy Markdown
Contributor

@linda-sap yes, please swap the logic - make encoding default and offer the possibility to not encode for possible workarounds.

@phanak-sap

phanak-sap commented Mar 8, 2023 •

Copy link
Copy Markdown
Contributor

@linda-sap Welcome to the contributors. This is a nice pull request. Could you just explain why is the encoding optional? Isn't just a bug to not always encode it?

@linda-sap yes, please swap the logic - make encoding default and offer the possibility to not encode for possible workarounds.

Agree, it is a bugfix, but a for five years old part that may be a possible unforeseen breaking change for somebody. At least the workaround option for run of behavior that existed so far. I would stress out more the fact that this was reproduced on SAP Gateway for particular service, and so far no issue for PUT/Batch payload for other odata services was created by any other library user. Perhaps they did not run into a problem with batch, but perhaps it is a SAP Gateway specific problem.

Removal of this configuration option may be IMHO a good subtask for 2.0 version - if encoding of everything in batch payload is as correct as the encoding in the url query params.

@phanak-sap

Copy link
Copy Markdown
Contributor

@linda-sap please add a changelog entry under the Unreleased as well, so it is not forgotten.

@phanak-sap

Copy link
Copy Markdown
Contributor

@linda-sap The linter job did not run, but it is important for this PR as well as a gate-keeper. I have fixed it in PR #239. Please update your branch as well, so we do not see this problem.

@linda-sap

Copy link
Copy Markdown
Contributor Author

@phanak-sap do I get you right, that you also prefer the option to make the encoding the default and leave the option to witch it off? I just want to be sure as also a good amount of tests need a change for this.

@phanak-sap

Copy link
Copy Markdown
Contributor

@phanak-sap do I get you right, that you also prefer the option to make the encoding the default and leave the option to witch it off? I just want to be sure as also a good amount of tests need a change for this.

Yes. I would probably start more defensively exactly like you did :), but the @jfilak suggestion makes for sense for long future. Bugfix, not a new feature mentality. Encoding by default, with new parameter option to run old behavior for possible workarounds.

@linda-sap

Copy link
Copy Markdown
Contributor Author

@jfilak @phanak-sap I changed it so the encoding is done by default and added the encoding to delete and getEntitySet request. Also I adopted the tests. However I'm not sure what the best way is to include the encoding or not in the get_value() function. Whether the general ODataHttpRequest class should handle it.

@phanak-sap

phanak-sap commented Mar 14, 2023 •

Copy link
Copy Markdown
Contributor

Hi @linda-sap,

you have failing one test in current PR - FAILED tests/test_service_v2.py::test_entity_get_value_1on1_with_proxy - requests.exceptions.ConnectionError: Connection refused by Responses - the call doesn't match any registered mock.

Please fix the linter build as well to be passing. You can run it locally as well, check "pylint" and "flake8": in the contributing guide

Two things from previous build were fixed, these remains. I am OK with # pylint: disable those rules for the EntityModifyRequest constructor.

pyodata/v2/service.py:578: [R0902(too-many-instance-attributes), EntityModifyRequest] Too many instance attributes (8/7)
pyodata/v2/service.py:586: [R0913(too-many-arguments), EntityModifyRequest.init] Too many arguments (8/7)

Comment thread docs/usage/querying.rst Resolved
Comment thread docs/usage/deleting.rst Resolved
Comment thread tests/test_service_v2.py Resolved
Comment thread tests/test_service_v2.py Resolved

@phanak-sap phanak-sap left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have small nitpick requests, builds also must be passing, but generally speaking, I am OK with this feature to be merged and released as is.

@linda-sap

Copy link
Copy Markdown
Contributor Author

@phanak-sap thanks a lot for your feedback!
Just so we are on the same page, the gut_value() functions (e.g. in test_entity_get_value_with_proxy and test_entity_get_value_1on1_with_proxy) do not return an object with an encoded path as those are not the requests to be sent.

@phanak-sap

Copy link
Copy Markdown
Contributor

@phanak-sap thanks a lot for your feedback! Just so we are on the same page, the gut_value() functions (e.g. in test_entity_get_value_with_proxy and test_entity_get_value_1on1_with_proxy) do not return an object with an encoded path as those are not the requests to be sent.

I do not understand "those are not the requests to be sent." correctly perhaps. Are we talking about method that basically add $value as a query parameter? That is different part of URL string.

Maybe this part of documentation will tie better the odata documentation and this library:
https://github.com/SAP/python-pyodata/blob/5a232b5013ce16c81996409c19d17311c7434203/docs/usage/urls.rst
https://www.odata.org/documentation/odata-version-2-0/uri-conventions/

Comment thread pyodata/v2/service.py Resolved
@linda-sap

Copy link
Copy Markdown
Contributor Author

@phanak-sap thanks a lot for your feedback! Just so we are on the same page, the gut_value() functions (e.g. in test_entity_get_value_with_proxy and test_entity_get_value_1on1_with_proxy) do not return an object with an encoded path as those are not the requests to be sent.

I do not understand "those are not the requests to be sent." correctly perhaps. Are we talking about method that basically add $value as a query parameter? That is different part of URL string.

Maybe this part of documentation will tie better the odata documentation and this library: https://github.com/SAP/python-pyodata/blob/5a232b5013ce16c81996409c19d17311c7434203/docs/usage/urls.rst https://www.odata.org/documentation/odata-version-2-0/uri-conventions/

Okay, I just wanted to make sure there is no need to also encode the url in these methods.

@codecov-commenter

codecov-commenter commented Apr 7, 2023 •

Copy link
Copy Markdown

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

❌ Patch coverage is 97.14286% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 92.31%. Comparing base (98b5c49) to head (0c70a6e).
⚠️ Report is 30 commits behind head on master.

Files with missing lines Patch % Lines
pyodata/v2/service.py 97.14% 1 Missing ⚠️
❗ Your organization needs to install the Codecov GitHub app to enable full functionality.
Additional details and impacted files
@@            Coverage Diff             @@
##           master     #243      +/-   ##
==========================================
- Coverage   92.34%   92.31%   -0.04%     
==========================================
  Files           6        6              
  Lines        2849     2874      +25     
==========================================
+ Hits         2631     2653      +22     
- Misses        218      221       +3     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@phanak-sap

Copy link
Copy Markdown
Contributor

@phanak-sap thanks a lot for your feedback! Just so we are on the same page, the gut_value() functions (e.g. in test_entity_get_value_with_proxy and test_entity_get_value_1on1_with_proxy) do not return an object with an encoded path as those are not the requests to be sent.

I do not understand "those are not the requests to be sent." correctly perhaps. Are we talking about method that basically add $value as a query parameter? That is different part of URL string.
Maybe this part of documentation will tie better the odata documentation and this library: https://github.com/SAP/python-pyodata/blob/5a232b5013ce16c81996409c19d17311c7434203/docs/usage/urls.rst https://www.odata.org/documentation/odata-version-2-0/uri-conventions/

Okay, I just wanted to make sure there is no need to also encode the url in these methods.

Well, .get_path() is now encoded in your PR, right? Rest three methods cover different URL parts, out of scope of this PR. And the get_value() from original question was resolved that it adding query parameter, so refers to different url part.

So I am under impression that everything is covered and this is just "communication noise" :). I will wait some time for possible reaction, but I will merge this today or tomorrow.

@linda-sap

Copy link
Copy Markdown
Contributor Author

@phanak-sap thanks a lot for your feedback! Just so we are on the same page, the gut_value() functions (e.g. in test_entity_get_value_with_proxy and test_entity_get_value_1on1_with_proxy) do not return an object with an encoded path as those are not the requests to be sent.

I do not understand "those are not the requests to be sent." correctly perhaps. Are we talking about method that basically add $value as a query parameter? That is different part of URL string.
Maybe this part of documentation will tie better the odata documentation and this library: https://github.com/SAP/python-pyodata/blob/5a232b5013ce16c81996409c19d17311c7434203/docs/usage/urls.rst https://www.odata.org/documentation/odata-version-2-0/uri-conventions/

Okay, I just wanted to make sure there is no need to also encode the url in these methods.

Well, .get_path() is now encoded in your PR, right? Rest three methods cover different URL parts, out of scope of this PR. And the get_value() from original question was resolved that it adding query parameter, so refers to different url part.

So I am under impression that everything is covered and this is just "communication noise" :). I will wait some time for possible reaction, but I will merge this today or tomorrow.

Correct, the get_path() is encoded and the others not.

@phanak-sap

Copy link
Copy Markdown
Contributor

Thank you for all the work.

@phanak-sap
phanak-sap merged commit 47cc1bf into SAP:master Apr 16, 2023
@phanak-sap phanak-sap modified the milestones: 1.11.0, 1.9.0 Apr 20, 2023
phanak-sap added a commit that referenced this pull request Nov 15, 2026
The problem and fix:

urllib.parse.quote() defaults to safe='/', so a slash inside a key value
(e.g. SoftwareComponents('/BAZ/FOO')) was left unencoded in the request
path. The entity-set name and key string were quoted as one string,
making it impossible to encode key-value slashes while preserving the
structural slashes that separate navigation segments.

Add encode_entity_path(), a parenthesis-depth-aware encoder: text outside
the key predicate is quoted with safe='/' (structural separators kept),
text inside (...) with safe='' (every reserved char, including /, encoded).
Output is byte-identical to the old quote() for keys without slashes, so
no existing path changes. Applied to EntityGetRequest, EntityDeleteRequest,
EntityModifyRequest and GetEntitySetRequest; batch inherits it via
get_path(). encode_path=False still bypasses encoding unchanged.

Additional notes:

This is outbound-only by design and has no from_literal-style counterpart:
encode_entity_path runs solely in get_path() to build request URLs. pyodata
never decodes a key back out of a path (the server does the percent-decoding;
the __next link is reused verbatim), so there is no reverse direction to
keep symmetric.

The encode_path=False workaround from PR #243 is intentionally left in
place for backward compatibility: callers who pre-encode keys and disable
encoding must keep working unchanged, and the flag also serves as a
raw-path override for non-conformant servers. Removing it is deferred to
a future major release.

Fixes #282
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants